﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using Epicor.Pub;

namespace Epicor.IME
{
    /// <summary>代码输入提示类</summary>
    public class IMEFun
    {
        /// <summary>钩子</summary>
        public HookLib KeybHook = null;
        /// <summary>选择列表窗体</summary>
        public IMESelect IMESelectF = null;
        /// <summary>选择列表窗体显示的最大数量</summary>
        public int maxShow = 10;
        /// <summary>选择列表窗体当前显示数量</summary>
        public int currShow = 0;
        /// <summary>已筛选列表</summary>
        public ArrayList selectList = new ArrayList();
        /// <summary>已筛选Hash表</summary>
        public Hashtable selectHash = new Hashtable();
        /// <summary>待选Hash表</summary>
        public Hashtable waitHash = new Hashtable();
        /// <summary></summary>
        public DataTable Test1 = new DataTable();
        /// <summary>是否能发送虚拟按键</summary>
        public bool canSetKey = false;

        private string[] cShap = "abstract,as,base,bool,break,byte,case,catch,char,checked,class,const,continue,decimal,default,delegate,do,double,else,enum,ecent,explicit,extern,false,finally,fixe,float,for,foreach,get,goto,if,implicit,in,int,interface,internal,is,lock,,namespace,new,null,object,out,override,partial,private,protected,public,readonly,ref,return,sbyte,sealed,set,short,sizeof,stackalloc,static,struct,switch,this,throw,true,try,typeof,uint,ulong,unchecked,unsafe,ushort,using,value,virtual,volatile,volatile,void,where,while,yield".Split(',');

        private int _cursorIndex = 0;
        /// <summary>输入光标位置</summary>
        public int cursorIndex
        {
            get
            {
                return _cursorIndex;
            }
            set
            {
                if (value < 0) _cursorIndex = 0;
                else if (value > inputStr.Length) _cursorIndex = inputStr.Length;
                else _cursorIndex = value;
            }
        }

        /// <summary>选择页</summary>
        public int _selectPage = 0;
        /// <summary>选择序号</summary>
        public int _selectIndex = 0;

        /// <summary>设置当前选择页</summary>
        public bool SetPage(int value) {
            int allP = (int)Math.Ceiling(Convert.ToDecimal(selectHash.Count) / maxShow);
            int _value = value;
            if (_value >= (allP - 1)) _value = allP - 1;
            if (_value < 0) _value = 0;
            if (_value != _selectPage)
            {
                _selectPage = _value;
                IMESelectF.LoadSelectList();
                return true;
            }
            return false;
        }
        /// <summary>下一页</summary>
        public bool NextPage()
        {
            if (SetPage(_selectPage + 1)) {
                _selectIndex = 0;
                IMESelectF.SetSelectLable();
                return true;
            }
            return false;
        }
        /// <summary>上一页</summary>
        public bool PrevPage()
        {
            if (SetPage(_selectPage - 1))
            {
                _selectIndex = currShow - 1;
                IMESelectF.SetSelectLable();
                return true;
            }
            return false;
        }
        ///<summary>设置当前选择项</summary>
        public bool SetIndex(int value)
        {
            int _value = value;
            if (currShow > 0)
            {
                if (_value >= currShow)
                {
                    if(!NextPage()) _value = currShow-1;
                    else return true;
                }
                else if (_value < 0)
                {
                    if(!PrevPage()) _value = 0;
                    else return true;
                }
            }
            if (_selectIndex != _value)
            {
                _selectIndex = _value;
                IMESelectF.SetSelectLable();
                return true;
            }
            return false;
        }
        /// <summary>下一项</summary>
        public bool NextIndex()
        {
            return SetIndex(_selectIndex + 1);
        }
        /// <summary>上一项</summary>
        public bool PrevIndex()
        {
            return SetIndex(_selectIndex - 1);
        }

        private string _inputStr = "";
        /// <summary>当前输入的字符串</summary>
        public string inputStr
        {
            get
            {
                return _inputStr;
            }
            set
            {
               _inputStr = value;
                if (!string.IsNullOrEmpty(value))
                {
                    LoadSelectList();
                    _selectIndex=0;
                    _selectPage=0;
                    IMESelectF.LoadSelectList();
                }
            }
        }

        /// <summary>获取按键字符</summary>
        public string GetKeyStr(Keys keyData, bool isShift,bool capsLock) {
            string keyStr = "";
            if (keyData >= Keys.A && keyData <= Keys.Z)//字符
            {
                string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                int idx = keyData.GetHashCode() - 65;
                keyStr = str[idx].ToString().ToLower();
                if(isShift!=capsLock) keyStr = str[idx].ToString();
            }
            else
            {
                string[] keyCode= "48,49,50,51,52,53,54,55,56,57,189,187,219,221,220,186,222,188,190,191,192".Split(',');
                string str1 = "0123456789-=[]\\;',./`";
                string str2 = ")!@#$%^&*(_+{}|:\"<>?~";
                for (int i = 0; i < keyCode.Length; i++) {
                    if (keyCode[i] == keyData.GetHashCode().ToString()) {
                        keyStr = str1[i].ToString();
                        if (isShift) keyStr = str2[i].ToString();
                        break;
                    }
                } 
            }
            return keyStr;
        }
        /// <summary>初始化数据 </summary>
        public void InitData()
        {
            canSetKey = false;
            _selectIndex = 0;
            _selectPage = 0;
            selectHash.Clear();
            selectList.Clear();
            inputStr = "";
            cursorIndex = 0;
            IMESelectF.DrawStr();
        }

        /// <summary>更新输入字符串</summary>
        public void SetChar(string chr)
        {
            inputStr = chr;
            cursorIndex = inputStr.Length;
            IMESelectF.DrawStr();
        }
        /// <summary>输入字符串添加字符</summary>
        public void AddChar(string chr)
        {
            inputStr = inputStr.Insert(cursorIndex, chr);
            cursorIndex += chr.Length;
            IMESelectF.DrawStr();
        }
        /// <summary>删除关闭前的字符</summary>
        public void BackChar()
        {
            inputStr = inputStr.Substring(0, cursorIndex - 1) + inputStr.Substring(cursorIndex);
            cursorIndex--;
            IMESelectF.DrawStr();
        }
        /// <summary>删除关闭后的字符</summary>
        public void DeleteChar()
        {
            inputStr = inputStr.Substring(0, cursorIndex) + inputStr.Substring(cursorIndex + 1);
            IMESelectF.DrawStr();
        }
        /// <summary>移动光标位置</summary>
        public void MoveChar(int n)
        {
            cursorIndex += n;
            IMESelectF.DrawStr();
        }
        /// <summary>获取选择列表中当前选中的字符串</summary>
        public string GetSelectText() {
            int idx = _selectPage * maxShow + _selectIndex;
            if (idx < selectList.Count)
                return selectList[_selectPage * maxShow + _selectIndex].ToString();
            else return inputStr;
        }
        /// <summary>根据字符串发送虚拟按键</summary>
        public void SendText(string text=null)
        {
            if (text == null)  text = GetSelectText();
            canSetKey = true;
            for (int i = 0; i < text.Length; i++)
            {
                Keys k = WinAPI32.VkKeyScan(text[i]);
                KeybHook.KeyPress(k);
            }
            canSetKey = false;
            InitData();
        }

        /// <summary>waitHash添加数据</summary>
        public void WaitHashAdd(string name, Type type=null)
        {
            if (type == null)
            {
                try
                {
                    var assembly = Assembly.LoadFrom(name);
                    var objs = assembly.GetTypes();
                    foreach (var type1 in objs)
                    {
                        waitHash[type1.Namespace] = new WaitData(type1.Namespace);
                        waitHash[type1.Namespace + "." + type1.Name] = new WaitData(type1.Namespace + "." + type1.Name, type1);
                    }
                }
                catch {

                }
            }
            else waitHash[name] = new WaitData(name, type);
        }


        /// <summary>加载选择列表</summary>
        public void LoadSelectList()
        {
            try
            {
                string iStr1 = inputStr.ToLower();//已输入的字符串
                string iStr2 = inputStr.Substring(inputStr.LastIndexOf('.') + 1).ToLower();//最后一个"."之后的数据
                selectHash.Clear();
                selectList.Clear();
                for (int i = 0; i < cShap.Length; i++)
                {
                    string str = cShap[i].ToLower();
                    if (str.StartsWith(iStr1))
                    {
                        selectHash[cShap[i]] =new WaitData(cShap[i]);
                    }
                }
                ArrayList akeys = new ArrayList(waitHash.Keys);
                foreach (string key in akeys)
                {
                    string keyStr = key.ToLower();
                    WaitData wm = (WaitData)waitHash[key];
                    if (keyStr.StartsWith(iStr1)) {
                        if (wm.type != null && keyStr == iStr1)
                        {
                            WaitData[] wmList = GetArrayByWaitHash(key);
                            foreach (WaitData wm1 in wmList)
                            {
                                waitHash[wm1.key] = wm1;
                                selectHash[wm1.key] = new WaitData(wm1.key, wm1.note);
                            }
                            wm.type = null;
                            waitHash[key] = wm;
                            
                        }
                        selectHash[key] = new WaitData(key, wm.note);
                    }
                    if ((iStr2.Length >= 3 && keyStr.StartsWith(iStr2))|| (keyStr.IndexOf("." + iStr1) >= 0))
                    {
                        selectHash[key] = new WaitData(key, wm.note);
                    }
                }
                selectList = new ArrayList(selectHash.Keys);
                selectList.Sort();
            }
            catch (Exception e) {
                MessageBox.Show(e.Message);
            }
        }

        private Hashtable dllXML = new Hashtable();
        private PubXML GetXML(string dllfile) {
            try
            {
                if (dllXML[dllfile] != null)
                {
                    if (!(dllXML[dllfile] is bool)) return (PubXML)dllXML[dllfile];
                }
                else
                {
                    string xmlFile = dllfile.Substring(0, dllfile.LastIndexOf('.') + 1) + "xml";
                    PubXML xml = new PubXML(xmlFile);
                    dllXML[dllfile] = xml;
                    return xml;
                }
            }
            catch
            {
                dllXML[dllfile] = false;
            }
            return null;
        }

        /// <summary>从waitHash中为选择列表添加数据</summary>
        public WaitData[] GetArrayByWaitHash(string key)
        {
            List<WaitData> list = new List<WaitData>();
            Type type = ((WaitData)waitHash[key]).type;
           
            //字段
            IEnumerable<FieldInfo> fieldinfo = type.GetRuntimeFields();
            foreach (FieldInfo f in fieldinfo)
            {
                if (f.IsPublic || key=="this")
                {
                    string name= f.DeclaringType.Namespace + "." + f.DeclaringType.Name;
                    string note = GetNote(f.DeclaringType, "F:" + name + "." + f.Name);
                    list.Add(new WaitData(key + "." + f.Name, f.FieldType, note));
                    if (typeof(ICollection).IsAssignableFrom(f.FieldType))
                    {
                        if (f.FieldType.IsArray)
                            list.Add(new WaitData(key + "." + f.Name + "[]", f.FieldType.GetElementType()));
                        else if (f.FieldType.IsGenericType)
                            list.Add(new WaitData(key + "." + f.Name + "[]", f.FieldType.GetGenericArguments()[0]));

                    }
                    
                }
            }
            //属性  
            IEnumerable<PropertyInfo> propertyinfo = type.GetRuntimeProperties();
            foreach (PropertyInfo p in propertyinfo)
            {
                if (p.CanRead)
                {
                    string name = p.DeclaringType.Namespace + "." +p.DeclaringType.Name;
                    string note = GetNote(p.DeclaringType, "P:" + name + "." + p.Name);
                    list.Add(new WaitData(key + "." + p.Name, p.PropertyType, note));
                    if (p.PropertyType.IsArray)
                        list.Add(new WaitData(key + "." + p.Name + "[]", p.PropertyType.GetElementType()));
                    else if (p.PropertyType.IsGenericType)
                        list.Add(new WaitData(key + "." + p.Name + "[]", p.PropertyType.GetGenericArguments()[0]));
                }
            }
            //方法  
            IEnumerable<MethodInfo> methodInfos = type.GetRuntimeMethods();
            foreach (MethodInfo mi in methodInfos)
            {
                if (mi.IsPublic || key == "this")
                {
                    ParameterInfo[] paramsInfo = mi.GetParameters();//得到指定方法的参数列表   
                    string str = "";
                    foreach (ParameterInfo prm in paramsInfo)
                    {
                        if (str != "") str += ",";
                        str += prm.ParameterType.Name;
                    }
                    string name = mi.DeclaringType.Namespace + "." + mi.DeclaringType.Name;
                    string note = GetNote(mi.DeclaringType, "M:" + name + "." + mi.Name);
                    list.Add(new WaitData(key + "." + mi.Name + "(" + str + ")", mi.ReturnType, note));
                    if (mi.ReturnType.IsArray)
                        list.Add(new WaitData(key + "." + mi.Name + "(" + str + ")[]", mi.ReturnType.GetElementType()));
                    else if (mi.ReturnType.IsGenericType)
                        list.Add(new WaitData(key + "." + mi.Name + "(" + str + ")[]", mi.ReturnType.GetGenericArguments()[0]));
                }
            }
            return list.ToArray();
        }
        /// <summary>获取注释</summary>
        public string GetNote(Type type, string name) {
            PubXML xml = GetXML(type.Assembly.Location);
            if (xml != null)
            {
                XmlNode node = xml.GetNode("doc/members/member[@name='" + name + "']/summary");
                if (node == null) node = xml.GetNode("doc/members/member[contains(@name,'" + name + "')]/summary");
                if (node != null) return node.InnerText;
            }
            return "";
        }
        
    }
    /// <summary>待选数据</summary>
    public class WaitData {
        /// <summary>待选数据key值</summary>
        public string key;
        /// <summary>待选数据类型</summary>
        public Type type;
        /// <summary>待选数据注释</summary>
        public string note;
        /// <summary>待选数据构造函数</summary>
        public WaitData(string _key,Type _type,string _note=null) {
            key = _key;
            type = _type;
            note = _note;
        }
        /// <summary>待选数据构造函数</summary>
        public WaitData(string _key, string _note = null)
        {
            key = _key;
            type = null;
            note = _note;
        }
    }
}
